package org.xx.armory.swing.components.verifiers;

import javax.swing.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import static org.xx.armory.commons.Validators.notNull;

/**
 * 用于处理输入组件验证的事件侦听器。
 * <p>当组件失去焦点时，检测输入内容是否合法，并设置验证状态，如果不合法则获取焦点。</p>
 * <p>当组件的内容变更时，检测输入内容是否合法，并设置验证状态。</p>
 * <p>组件的内容需要被提交时，检测输入内容是否合法，并设置验证状态，如果不合法则获取焦点。</p>
 */
public class InputComponentVerificationAdapter
        implements FocusListener {
    private JComponent component;
    private TextVerifier verifier;

    /**
     * 构造处理输入组件验证的事件侦听器。
     *
     * @param component
     *         输入组件。
     * @param verifier
     *         验证执行类。
     * @throws IllegalArgumentException
     *         如果参数{@code component}或者{@code verifier}是{@code null}。
     */
    public InputComponentVerificationAdapter(
            JComponent component,
            TextVerifier verifier
    ) {
        this.component = notNull(component, "component");
        this.verifier = notNull(verifier, "verifier");

        component.addFocusListener(this);
    }

    /**
     * 获取关联的输入组件。
     *
     * @return 关联的输入组件。
     */
    public final JComponent getComponent() {
        return this.component;
    }

    /**
     * 对组件进行验证。
     *
     * @return 是否验证通过。
     */
    public VerifiedStatus verify() {
        final VerifiedStatus status = this.verifier.verify(this.component);

        statusChanged(status);

        return status;
    }

    /**
     * 组件的输入内容检测结果被重置时执行此方法。
     */
    protected void statusReset() {
    }

    /**
     * 组件的输入内容检测结果发生变化时执行此方法。
     *
     * @param status
     *         当前检测结果。
     */
    protected void statusChanged(
            VerifiedStatus status
    ) {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void focusGained(
            FocusEvent event
    ) {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void focusLost(
            FocusEvent event
    ) {
        final VerifiedStatus status = this.verifier.verify(this.component);

        statusChanged(status);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return "adapter {name=" + this.component.getName() + ",verifier=" + this.verifier + "}";
    }
}
